package com.star.oauth2.resource.controller;

import com.star.oauth2.resource.model.Message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 消息API控制器
 * 
 * 提供消息的CRUD操作
 * 通过OAuth2的scope控制访问权限
 * 
 * @author star
 */
@Slf4j
@RestController
@RequestMapping("/api/messages")
public class MessageController {

    // 内存存储消息（实际项目应使用数据库）
    private final ConcurrentHashMap<Long, Message> messageStore = new ConcurrentHashMap<>();
    private final AtomicLong idGenerator = new AtomicLong(1);

    /**
     * 获取消息列表
     * 需要 message.read 权限
     */
    @GetMapping
    @PreAuthorize("hasAuthority('SCOPE_message.read')")
    public List<Message> getMessages(Authentication authentication) {
        logAuthenticationInfo(authentication, "读取消息列表");
        return new ArrayList<>(messageStore.values());
    }

    /**
     * 根据ID获取消息
     * 需要 message.read 权限
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('SCOPE_message.read')")
    public Message getMessage(@PathVariable Long id, Authentication authentication) {
        logAuthenticationInfo(authentication, "读取消息: " + id);
        Message message = messageStore.get(id);
        if (message == null) {
            throw new RuntimeException("消息不存在: " + id);
        }
        return message;
    }

    /**
     * 创建新消息
     * 需要 message.write 权限
     */
    @PostMapping
    @PreAuthorize("hasAuthority('SCOPE_message.write')")
    public Message createMessage(@RequestBody Message message, Authentication authentication) {
        logAuthenticationInfo(authentication, "创建消息");
        
        message.setId(idGenerator.getAndIncrement());
        message.setCreatedAt(LocalDateTime.now());
        message.setCreatedBy(getUsername(authentication));
        
        messageStore.put(message.getId(), message);
        
        log.info("创建消息成功: {}", message);
        return message;
    }

    /**
     * 更新消息
     * 需要 message.write 权限
     */
    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('SCOPE_message.write')")
    public Message updateMessage(@PathVariable Long id, 
                                  @RequestBody Message message,
                                  Authentication authentication) {
        logAuthenticationInfo(authentication, "更新消息: " + id);
        
        Message existingMessage = messageStore.get(id);
        if (existingMessage == null) {
            throw new RuntimeException("消息不存在: " + id);
        }
        
        existingMessage.setContent(message.getContent());
        existingMessage.setUpdatedAt(LocalDateTime.now());
        existingMessage.setUpdatedBy(getUsername(authentication));
        
        log.info("更新消息成功: {}", existingMessage);
        return existingMessage;
    }

    /**
     * 删除消息
     * 需要 message.write 权限
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('SCOPE_message.write')")
    public void deleteMessage(@PathVariable Long id, Authentication authentication) {
        logAuthenticationInfo(authentication, "删除消息: " + id);
        
        Message removed = messageStore.remove(id);
        if (removed == null) {
            throw new RuntimeException("消息不存在: " + id);
        }
        
        log.info("删除消息成功: {}", removed);
    }

    /**
     * 记录认证信息
     */
    private void logAuthenticationInfo(Authentication authentication, String action) {
        if (authentication != null && authentication.getPrincipal() instanceof Jwt jwt) {
            log.info("用户 [{}] 执行操作: {}, Scopes: {}", 
                    jwt.getClaimAsString("sub"), 
                    action,
                    jwt.getClaimAsStringList("scope"));
        }
    }

    /**
     * 获取用户名
     */
    private String getUsername(Authentication authentication) {
        if (authentication != null && authentication.getPrincipal() instanceof Jwt jwt) {
            return jwt.getClaimAsString("sub");
        }
        return "unknown";
    }

}

